Galileo Computing < openbook > Galileo Computing - Professionelle Bücher. Auch für Einsteiger.

...powered by www.netzwerkartist.de...

 << zurück
Visual C# 2005 von Andreas Kühnel
Das umfassende Handbuch
Buch: Visual C# 2005

Visual C# 2005
1.320 S., mit 2 CDs, 59,90 Euro
Galileo Computing
ISBN 3-89842-586-X
gp Kapitel 12 Arbeiten mit Dateien und Streams
  gp 12.1 Namespaces der Ein- bzw. Ausgabe
    gp 12.1.1 Das Behandeln von Ausnahmen bei E/A-Operationen
  gp 12.2 Laufwerke, Verzeichnisse und Dateien
    gp 12.2.1 Die Klasse »File«
    gp 12.2.2 Die Klasse »FileInfo«
    gp 12.2.3 Die Klassen »Directory« und »DirectoryInfo«
    gp 12.2.4 Die Klasse »Path«
    gp 12.2.5 Die Klasse »DriveInfo«
    gp 12.2.6 Die Klasse »SpecialDirectories«
  gp 12.3 Die »Stream«-Klassen
    gp 12.3.1 Die abstrakte Klasse »Stream«
    gp 12.3.2 Die von »Stream« abgeleiteten Klassen im Überblick
    gp 12.3.3 Die Klasse »FileStream«
  gp 12.4 Die Klassen »TextReader« und »TextWriter«
    gp 12.4.1 Die Klasse »StreamWriter«
    gp 12.4.2 Die Klasse »StreamReader«
    gp 12.4.3 Die Klassen »StringWriter« und »StringReader«
  gp 12.5 Die Klassen »BinaryReader« und »BinaryWriter«
    gp 12.5.1 Komplexe binäre Dateien
  gp 12.6 Synchrone und asynchrone Operationen
    gp 12.6.1 Beispielprogramm eines asynchronen Schreibvorgangs


Galileo Computing

12.2 Laufwerke, Verzeichnisse und Dateiedowntop

Die Klassenbibliothek des .NET Frameworks unterstützt den Entwickler mit mehreren Klassen, die Laufwerke, Verzeichnisse und Dateien beschreiben. Diese wollen wir als Erstes ansehen. Dabei handelt es sich um:

gp  File
gp  FileInfo
gp  Directory
gp  DirectoryInfo
gp  Path
gp  DriveInfo
gp  SpecialDirectories

File bzw. FileInfo und Directory bzw. DirectoryInfo liefern sehr ähnliche Daten über die zurück. Bei File/FileInfo handelt es um Daten, die eine Datei betreffen, bei Directory/DirectoryInfo um Daten von Verzeichnissen. Möchten Sie Pfadangaben ermitteln, hilft Ihnen Path weiter. Neu im .NET Framework sind DriveInfo, um Laufwerksinformationen abzufragen, und SpecialDirectories, um die Pfade Windows-eigener Verzeichnisse zu erhalten.


Galileo Computing

12.2.1 Die Klasse »File«  downtop

Die nicht ableitbare Klasse File stellt nur statische Methoden zur Verfügung, die Methoden von FileInfo sind Instanzmethoden und werden über eine Objektreferenz aufgerufen. Funktionell sind sich beide Klassen jedoch ähnlich und unterscheiden sich nicht gravierend.

Methoden der Klasse »File«

Mit den Klassenmethoden von File lässt sich eine Datei erstellen, kopieren, löschen usw. Sie können auch die Attribute einer Datei lesen oder setzen, und – was auch sehr wichtig ist – Sie können eine Datei öffnen. Um das Lesen und Schreiben von Dateien zu vereinfachen, wurde die Klasse mit dem .NET Framework 2.0 um einige Methoden erweitert. In Tabelle 12.1 sind die wichtigsten samt Rückgabetyp aufgeführt.


Tabelle 12.1   Methoden der Klasse »File«

Methode Rückgabetyp Beschreibung
AppendAllText void Öffnet eine Datei, fügt die angegebene Zeichenfolge an die Datei an.
AppendText StreamWriter Hängt Text an eine existierende Datei an.
Copy void Kopiert eine bestehende Datei an eine andere Speicherlokalität.
Create FileStream Erzeugt eine Datei in einem angegebenen Pfad.
CreateText StreamWriter Erstellt oder öffnet eine Textdatei.
Delete void Löscht eine Datei.
Exists Boolean Gibt einen booleschen Wert zurück, der false ist, wenn die angegebene Datei nicht existiert.
GetAttributes FileAttributes Liefert das Bitfeld der Dateiattribute.
GetCreationTime DateTime Liefert das Erstellungsdatum und die Uhrzeit einer Datei.
GetLastAccessTime DateTime Liefert Datum und Uhrzeit des letzten Zugriffs.
GetLastWriteTime DateTime Liefert Datum und Uhrzeit des letzten Schreibzugriffs.
Move void Verschiebt eine Datei in einen anderen Ordner oder benennt sie um.
Open FileStream Öffnet eine Datei.
OpenRead FileStream Öffnet eine Datei zum Lesen.
OpenText StreamReader Öffnet eine Textdatei zum Lesen.
OpenWrite FileStream Öffnet eine Datei zum Schreiben.
ReadAllBytes byte[] Öffnet eine Binärdatei, liest den Inhalt der Datei in ein Byte-Array ein.
ReadAllLines string[] Öffnet eine Textdatei, liest alle Zeilen der Datei in ein Zeichenfolgen-Array ein.
ReadAllText string Öffnet eine Textdatei, liest alle Zeilen der Datei in eine Zeichenfolge ein und schließt dann die Datei.
SetAttributes void Setzt Dateiattribute.
SetCreationTime void Setzt Erstellungsdatum und -uhrzeit.
SetLastAccessTime void Setzt Datum und Uhrzeit des letzten Zugriffs.
SetLastWriteTime void Setzt Datum und Uhrzeit des letzten Schreibzugriffs.
WriteAllBytes void Erstellt eine neue Datei, schreibt das angegebene Byte-Array in die Datei.
WriteAllLines void Erstellt eine neue Datei, schreibt das angegebene Zeichenfolgen-Array in die Datei.
WriteAllText void Erstellt eine neue Datei, schreibt das angegebene Zeichenfolgen-Array in die Datei.

Wie Sie sehen können, geben viele Methoden ein Stream-Objekt zurück. Das hat seinen Grund, denn mit einer geöffneten Datei will man arbeiten, sei es um den Inhalt zu lesen oder etwas in die Datei zu schreiben. Diese Operationen setzen aber einen Stream voraus, was das .NET Framework durch die Definition verschiedener Stream-Klassen abdeckt. Ein FileStream beschreibt dabei einfache Bytesequenzen, ein StreamReader basiert auf einer Textdatei.

Einige typische Dateioperationen wollen wir uns nun im Detail ansehen.

Kopieren einer Datei

Dem Kopieren einer Datei dient die Methode Copy, die einfach überladen ist:


public static void Copy(string, string);
public static void Copy(string, string, bool);

Beide Versionen erwarten als erstes Argument die Übergabe des Dateinamens der zu kopierenden Datei. Befindet sich die zu kopierende Datei in keinem bekannten Suchpfad, muss der gesamte Zugriffspfad beschrieben werden.

Im zweiten Argument müssen Sie das Zielverzeichnis und den Namen der Dateikopie angeben. Den Namen der kopierten Datei dürfen Sie gemäß den systemspezifischen Richtlinien festlegen, er muss nicht mit dem Ursprungsnamen der Datei übereinstimmen. Versucht man, ein Ziel anzugeben, in dem bereits eine gleichnamige Datei existiert, wird die Ausnahme DirectoryNotFoundException ausgelöst.


// löst die Ausnahme DirectoryNotFoundException aus, wenn im
// Zielverzeichnis bereits eine gleichnamige Datei vorhanden ist 
File.Copy("C:\\Test.txt", "D:\\Test.txt");


Hinweis   Wenn Sie die Pfadangabe in einem string-Literal festlegen, müssen Sie beachten, dass das einfache Backslash-Zeichen in einem Literal als Escape-Zeichen interpretiert wird. Sie müssen deshalb zwei Backslashes hintereinander angeben oder alternativ der Zeichenfolge ein »@«-Zeichen voranstellen. File.Copy(@"C:\Test.txt", @"D:\Test.txt");

Sie können die Methode Copy auch einsetzen, wenn im Zielverzeichnis bereits eine Datei existiert, die denselben Namen hat wie die Datei, die Sie im zweiten Argument angeben. Dann müssen Sie die Überladung von Copy benutzen, die im dritten Parameter einen booleschen Wert erwartet. Übergeben Sie hier true, wird keine Ausnahme ausgelöst und die bereits vorhandene Datei durch den Inhalt der im ersten Argument übergebenen Datei überschrieben.

Im folgenden Beispiel wird der Anwender dazu aufgefordert, den Pfad und das Zielverzeichnis der zu kopierenden Datei einzugeben. Dabei könnte es zu verschiedenen Ausnahmen kommen, beispielsweise wenn die zu kopierende Datei nicht gefunden wird oder der Anwender das Quell- oder Zielverzeichnis an der Konsole nicht angibt. Diese Fehler werden im Code aufgefangen und behandelt. Damit auch möglicherweise unberücksichtigte Fehler nicht zum vorzeitigen Ende der Laufzeit der Anwendung führen, wird im letzten catch-Block jede weitere Ausnahme, die im Zusammenhang mit den IO-Operationen steht, behandelt.


// ----------------------------------------------------------
// Beispiel: ...\ Kapitel 12\CopyFile
// ----------------------------------------------------------
class Program {
  static void Main(string[] args) {
    string source, destination;
    Console.Write("Datei zum Kopieren: ");
    source = Console.ReadLine();
    Console.Write("Kopierziel: ");
    destination = Console.ReadLine();
    try {
      // -------------Datei kopieren---------------
      File.Copy(source, destination);
      Console.WriteLine("Erfolgreich kopiert.");
    }
    catch(DirectoryNotFoundException e) {
      // Zielverzeichnis nicht gefunden
      Console.WriteLine(e.Message);
    }
    catch(FileNotFoundException e) {
      // Die zu kopierende Datei wird nicht gefunden
      Console.WriteLine(e.Message);
    }
    catch(ArgumentException e) {
      // Ziel- oder Quellverzeichnis nicht angegeben
      Console.WriteLine(e.Message);
    }
    catch (IOException e) { 
      // Eine unbehandelte Ausnahme ist aufgetreten
      Console.WriteLine(e.Message);
    }
    Console.ReadLine();
  }
}

Als Pfad ist neben der absoluten Angabe, die auch Suchpfade einschließt, eine relative Angabe zulässig. Relative Pfadangaben beziehen sich dabei auf das aktuelle Arbeitsverzeichnis, in dem sich die ausführbare Datei der Anwendung befindet. Normalerweise werden Sie als Entwickler nicht wissen, in welchem Pfad der Anwender das Programm installiert hat. Um die Zeichenfolge darauf zu erhalten, können Sie sich diese mit


Directory.GetCurrentDirectory();

besorgen. Anschließend wird noch der Dateiname angehängt, bei dem es zu berücksichtigen gilt, dass GetCurrentDirectory nicht mit einem Backslash (\) abschließt.


string source = Directory.GetCurrentDirectory() + @"\MyDoc.txt";
string destination = @"C:\DuplicatedDoc.txt";
File.Copy(source, destination);

Löschen einer Datei

Die Syntax der Methode Delete zum Löschen einer Datei lautet wie folgt:


public static void Delete(string path);

Der Parameter path erwartet entweder die absolute oder die relative Pfadangabe. Ungültige Angaben können auch hier unterschiedliche Ausnahmen auslösen.


File.Delete(@"C:\MyDoc.txt");

Verschieben einer Datei

Die Syntax der Methode Move zum Verschieben einer Datei ähnelt der der Methode Copy:


public static void Move(string, string);

Dem ersten Parameter wird die zu verschiebende Datei übergeben, dem zweiten der neue Pfad der Datei.

Mit Move lassen sich Dateien nicht nur aus einem Quell- in ein spezifiziertes Zielverzeichnis verschieben, denn die Methode kann auch zum Umbenennen von Dateinamen benutzt werden. Eine spezielle Methode dafür wird von der Klasse File nicht angeboten.


// Datei wird umbenannt
File.Move(@"C:\MyDoc.txt", @"C:\Test.Doc");

Prüfen, ob eine Datei existiert

Beabsichtigen Sie, eine bestimmte Datei zu öffnen, stellt sich zunächst die Frage, ob eine Datei dieses Namens in dem angegebenen Pfad tatsächlich existiert. Die Klasse File veröffentlicht zur Beantwortung die Methode Exists, die den booleschen Wert false zurückliefert, wenn die Datei nicht gefunden wird.


string strFile = @"C:\MyFile.txt";
if (File.Exists(strFile)) {
  // Datei existiert im angegebenen Pfad 
}

Eine ähnliche Codesequenz dürfte in jedem Programm sinnvoll sein, in dem eine Operation die Existenz einer Datei zwingend voraussetzt. Das erspart die Codierung einer Ausnahmebehandlung.

Öffnen einer Datei

Bevor Sie den Inhalt einer Datei lesen bzw. ändern können, muss diese geöffnet werden. Eine Datei zu öffnen, sagt aber noch nichts darüber aus, was ein Benutzer mit dieser Datei anfangen darf – ob er sie nur lesen kann oder auch das Recht besitzt, sie zu editieren. Auch das Verhalten bei mehreren gleichzeitigen Zugriffen ist ein Punkt, dem unter bestimmten Umständen Beachtung geschenkt werden muss.

Die Klasse File stellt insgesamt vier Methoden zur Verfügung, die das Öffnen einer Datei bewirken: OpenRead, OpenText, OpenWrite sowie die mehrfach überladene Methode Open. Widmen wir unsere Aufmerksamkeit zuerst der letztgenannten.


public static FileStream Open(string path, FileMode mode);
public static FileStream Open(string path, FileMode mode,
                              FileAccess access);
public static FileStream Open(string path, FileMode mode,
                              FileAccess access, FileShare share);

Dem Parameter path wird beim Aufruf die Pfadangabe als Zeichenfolge mitgeteilt, bestehend aus Pfad und Dateiname.

Für das Öffnen einer Datei ist das Betriebssystem zuständig, das wissen muss, wie es die Datei öffnen soll. Der mode-Parameter vom Typ FileMode steuert dieses Verhalten. Dabei handelt es sich um eine im Namespace System.IO definierte Enumeration, die insgesamt sechs Konstanten definiert (siehe Tabelle 12.2).


Tabelle 12.2   Die Konstanten der Enumeration »FileMode«

FileMode-Konstante Beschreibung
Append Öffnet eine bestehende Datei und setzt den Dateizeiger an das Dateiende. Damit wird das Anhängen von Dateninformationen an die Datei ermöglicht. Existiert die Datei noch nicht, wird sie erzeugt.
Create Erzeugt eine neue Datei. Existiert bereits eine gleichnamige, wird diese überschrieben.
CreateNew Erzeugt in jedem Fall eine neue Datei. Existiert im angegebenen Pfad bereits eine gleichnamige, wird die Ausnahme IOException ausgelöst.
Open Öffnet eine bestehende Datei. Wird diese unter der Pfadangabe nicht gefunden, kommt es zur Ausnahme FileNotFoundException.
OpenOrCreate Öffnet eine bestehende Datei. Sollte diese im angegebenen Pfad nicht existieren, wird eine neue erzeugt.
Truncate Öffnet eine Datei und löscht deren Inhalt. Nachfolgende Leseoperationen führen zu einer Ausnahmeauslösung.

Der mode-Parameter beschreibt das Verhalten des Betriebssystems beim Öffnen einer Datei, jedoch nicht, was mit dem Inhalt der Datei geschehen soll. Soll er nur gelesen werden, oder möchte der Anwender in die Datei schreiben? Vielleicht sind auch beide Operationen gleichzeitig gewünscht. Diese Festlegung wird im Parameter access getroffen, der ebenfalls auf einer Aufzählung basiert – FileAccess. Diese hat nur drei Mitglieder: Read, Write und ReadWrite.


Tabelle 12.3   Die Konstanten der Enumeration »FileAccess«

FileAccess-Konstante Beschreibung
Read Datei wird für den Lesezugriff geöffnet.
Write Datei wird für den Schreibzugriff geöffnet.
ReadWrite Datei wird für den Lese- und Schreibzugriff geöffnet.

Eine Datei, die mit FileAccess.Read geöffnet wird, ist schreibgeschützt. Eine lesegeschützte Datei, deren Inhalt verändert werden soll, wird mit FileAccess.Write geöffnet. Die dritte Konstante FileAccess.ReadWrite beschreibt sowohl einen lesenden als auch schreibenden Zugriff.

Versuchen Sie, auf eine mit FileAccess.Write geöffnete Datei lesend zuzugreifen, wird die Exception NotSupportedException ausgelöst. Lassen Sie sich durch diese unglückliche Namensgebung nicht irritieren, und kommen Sie nicht auf den Gedanken, es handele sich um einen Fehler, der nicht unterstützt wird (je nach Betonung des Namens könnte man sehr schnell zu dieser Annahme gelangen). Diese Exception beschreibt nur eine Operation, die auf eine geöffnete Datei ausgeführt, jedoch aufgrund des Öffnungsmodus nicht unterstützt wird (besser wäre hier wohl der Name NotSupportedFileAccessException gewesen).

Kommen wir nun zum letzten Parameter der Open-Methode – share. Die Zeiten der unabhängigen lokalen Rechner neigt sich schon seit langem dem Ende zu, Netzwerke sind in den Unternehmen allgemeiner Standard. Infolgedessen muss der Umstand Berücksichtigung finden, dem man bis vor einigen Jahren meist keine besondere Beachtung geschenkt hat: Mehrere Anwendungen oder mehrere Threads versuchen, gleichzeitig auf dieselbe Datei zuzugreifen.

share beschreibt das Verhalten der Datei, wenn nach dem ersten Öffnen weitere Zugriffe auf die Datei erfolgen. Wie schon von den beiden vorher besprochenen Parametern bekannt, wird auch dieser durch Konstanten beschrieben, die einer Enumeration des Namespace System.IO zugerechnet werden – FileShare. Die Mitglieder ähneln denen der Enumeration FileAccess, werden aber um ein weiteres ergänzt (genau genommen sind es zwei, aber der zweite spielt für uns keine Rolle).


Tabelle 12.4   Die Konstanten der Enumeration »FileShare«

FileShare-Konstante Beschreibung
None Alle weiteren Versuche, diese Datei zu öffnen, werden konsequent abgelehnt.
Read Diese Datei darf von anderen Anwendungen oder Threads nur zum Lesen geöffnet werden.
Write Diese Datei darf von anderen Anwendungen oder Threads nur zum Editieren geöffnet werden.
ReadWrite Diese Datei darf von anderen Anwendungen oder Threads sowohl zum Lesen als auch zum Editieren geöffnet werden.

Damit haben wir die Parameterliste der Methode Open abgehandelt, Ihnen stehen alle Hilfsmittel zur Verfügung, eine beliebige Datei unter bestimmten Voraussetzungen zu öffnen. Führen Sie sich aber vor Augen, dass eine geöffnete Datei nicht automatisch ihre Dateninformationen liefert oder sich manipulieren lässt. Diese Operationen haben mit dem Vorgang des Öffnens noch nichts zu tun, setzen ihn aber voraus. Beachten Sie in diesem Zusammenhang, dass Operationen, die den Inhalt einer Datei beeinflussen, auf dem zurückgegebenen Objekt vom Typ FileStream ausgeführt werden.

In der folgenden Codezeile wird exemplarisch eine Datei mit Open geöffnet:


FileStream fs = File.Open(@"C:\MyTestfile.txt", 
    FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);

Die Parameter besagen, dass die Datei MyTestfile.txt im Stammverzeichnis C:\ geöffnet werden soll – falls es dort eine solche gibt. Wenn nicht, wird sie neu erzeugt. Der Inhalt der Datei lässt sich nach dem Öffnen sowohl lesen als auch ändern. Gleichzeitig werden weitere Zugriffe auf die Datei strikt unterbunden.

Weitere Methoden zum Öffnen einer Datei

File.Open ist die allgemeinste Variante, eine Datei zu öffnen. Die Klasse File bietet aber drei weitere, spezialisiertere Formen an:


public static FileStream OpenRead(string path);
public static StreamReader OpenText(string path);
public static FileStream OpenWrite(string path);

Mit OpenRead wird die angegebene Datei zum Lesen geöffnet, mit OpenWrite zum Schreiben. Diese beiden Methoden können, wie auch die Open-Methode, Dateien beliebigen Inhalts öffnen. OpenText hingegen ist auf Textdateien spezialisiert.

Der Rückgabetyp der Methode OpenText ist ein StreamReader. Damit unterscheidet sich diese Methode von den anderen, welche die Referenz auf ein FileStream-Objekt liefern. Wir wollen uns an dieser Stelle noch nicht mit den Details dieser beiden Klassen beschäftigen – das folgt später in diesem Kapitel. Dennoch sollten Sie schon den Unterschied zwischen diesen beiden Streams kennen.

Ein Objekt vom Typ StreamReader liest einzelne Zeichen (char) oder Zeichenfolgen aus einem Stream. Anders formuliert: Diese Klasse eignet sich für Textdateien. Im Gegensatz dazu wird der Datenstrom eines FileStream-Objekts byteweise gelesen. Die Interpretation dessen, was der Datenstrom beinhaltet, steht auf einem anderen Blatt. Es kann sich dabei natürlich auch um ASCII-Zeichen handeln, möglicherweise müssen die empfangenen Bytes aber auch als int oder float interpretiert werden.

Kommen wir zurück zu den vier Methoden zum Öffnen von Dateien. Open, OpenRead und OpenWrite liefern eine Referenz auf ein FileStream-Objekt, sind in dieser Hinsicht also gleichwertig. Sie kommen dann zum Einsatz, wenn der Datenstrom Byte für Byte empfangen werden muss. Was ankommt, bedarf einer »Nachbearbeitung«, ansonsten können die Informationen nicht ausgewertet werden. Open ist die allgemeinste Variante, OpenRead und OpenWrite stellen insofern nur eine Teilmenge der Möglichkeiten von Open dar.

Die vierte Methode, OpenText, ist eine spezialisierte Variante und nur für Textdateien geeignet. Dem wollen wir uns im folgendem Abschnitt widmen.

Öffnen einer Textdatei

Im folgenden Beispiel soll eine Textdatei geöffnet und der Inhalt an der Konsole ausgeben werden. Dazu wird im Code OpenText aufgerufen und die zurückgelieferte Referenz einer Objektvariablen des Typs StreamReader zugewiesen. Die Operationen, die im Zusammenhang mit dieser Klasse stehen, sollen uns an dieser Stelle noch nicht weiter interessieren.


// -----------------------------------------------------------
// Beispiel: ...\Kapitel 12\TextdateiLesen
// -----------------------------------------------------------
class Program {
  static void Main(string[] args) {
    // Benutzereingabe
    Console.Write("Geben Sie die zu öffnende Datei an: ");
    string strFile = Console.ReadLine();
    // prüfen, ob die angegebene Datei existiert
    if (! File.Exists(strFile)) {
      Console.WriteLine("Die Datei {0} existiert nicht!",  strFile);
      Console.ReadLine();
      return;
    }
    // Datei öffnen
    StreamReader sr = File.OpenText(strFile);
    string lineInput;
    lineInput = sr.ReadLine();
    // zeilenweise Ausgabe an der Konsole
    while (lineInput != null) {
      Console.WriteLine(lineInput);
      lineInput = sr.ReadLine();
    }
    Console.WriteLine("---- Programm- und Dateiende ----");
    Console.ReadLine();
    sr.Close();
  }
}

Nach dem Start des Programms wird der Anwender an der Konsole zur Eingabe der Pfadangabe zu einer existierenden Textdatei aufgefordert. Nach der Bestätigung der Eingabe wird zuerst mit File.Exists geprüft, ob die Datei im spezifizierten Pfad überhaupt vorhanden ist. Gibt es die Datei nicht, erscheint eine entsprechende Meldung an der Konsole, und das Programm wird geschlossen.

Existiert die Datei, wird sie mit File.OpenText geöffnet. In einer Schleife wird die Datei zeilenweise mit der Methode ReadLine des StreamReader-Objekts bis zum Dateiende eingelesen. Danach wird die Schleife beendet.

Der einfachste Weg, in eine Datei zu schreiben und daraus zu lesen

Der Weg, um in eine Datei zu schreiben oder eine Datei zu lesen, bedurfte bisher immer mehrerer Codezeilen. Eigentlich viel zu viel Aufwand, um eben schnell eine einfache Dateioperation auszuführen. Das .NET Framework wartet mit einer kaum vollständig zu beschreibenden Vielzahl an Möglichkeiten, die uns das Leben als Entwickler vereinfachen sollen. Die Verbesserungen betreffen auch die Klasse File, die im Vergleich mit .NET Framework 1.0/1.1 um mehrere Methoden ergänzt wurde, um mit nur einer einzigen Zeile Code Daten in eine Datei zu schreiben beziehungsweise mit einer Zeile Code Daten einzulesen. Es handelt sich hier um die Methoden ReadAllBytes, ReadAllLines und ReadAlltext zum Lesen und WriteAllBytes, WriteAllLines und WriteAllText zum schreiben.

Mit der simplen Anweisung


File.WriteAllText(@"C:\MyTextFile.txt", strText);

können Sie bereits den Inhalt der Variablen strText in die angegebene Datei schreiben. Existiert die Datei schon, wird sie einfach überschrieben.

Genauso einfach ist auch die inhaltliche Auswertung der Datei:


Console.WriteLine(File.ReadAllText(@"C:\MyTextFile.txt"));


Galileo Computing

12.2.2 Die Klasse »FileInfo«  downtop

Die ebenfalls nicht ableitbare Klasse FileInfo ist das Pendant zu der im vorigen Abschnitt beschriebenen Klasse File. Während letztere nur statische Methoden veröffentlicht, beziehen sich die der Klasse FileInfo auf eine konkrete Dateiinstanz. Um diese zu erhalten, steht nur ein Konstruktor zur Verfügung, dem Sie als Argument die Pfadangabe zu der Datei übergeben müssen, z.B.:


FileInfo myFile = new FileInfo(@"C:\TestDir\Testfile.txt");

Der Konstruktor prüft nicht, ob die Datei tatsächlich existiert. Bevor Sie Operationen auf das Objekt ausführen, sollten Sie deshalb in jedem Fall vorher mit Exists sicherstellen, dass die Datei existiert.


if (! myFile.Exists) {
  // Datei existiert nicht
}

Während Exists in der Klasse File als Methode implementiert ist, der die Pfadangabe beim Aufruf übergeben werden muss, handelt es sich in der Klasse FileInfo um eine schreibgeschützte Eigenschaft des FileInfo-Objekts.

Die Eigenschaften eines »FileInfo«-Objekts

Die Klasse FileInfo wird nicht direkt aus Object abgeleitet, sondern aus der Klasse FileSystemInfo. Sie erbt daher alle Mitglieder dieser Basisklasse, die gleichzeitig auch Basisklasse der Klasse DirectoryInfo ist, die wir weiter unten noch ansprechen.

FileInfo veröffentlicht eine Reihe von Instanzeigenschaften, denen der Zustand der Datei entnommen werden kann, die das FileInfo-Objekt beschreibt. So können Sie beispielsweise die Länge der Datei abfragen oder sich ein Objekt vom Typ Directory zurückgeben lassen (ein Directory-Objekt beschreibt ein Verzeichnis als Objekt, ähnlich wie FileInfo eine Datei).


Tabelle 12.5   Die Eigenschaften eines Objekts vom Typ »FileInfo«

Eigenschaft Beschreibung
Attributes Ermöglicht das Setzen oder Auswerten der Dateiattribute (Hidden, Archive, ReadOnly usw.).
CreationTime Liefert oder setzt das Erstellungsdatum der Datei.
Directory Liefert eine Instanz des Verzeichnisses.
DirectoryName Liefert eine Zeichenfolge mit der vollständigen Pfadangabe, jedoch ohne den Dateinamen.
Extension Liefert die Dateierweiterung einschließlich des vorangestellten Punktes.
FullName Gibt einen String mit der vollständigen Pfadangabe einschließlich des Dateinamens zurück.
LastAccessTime Liefert oder setzt die Zeit des letzten Zugriffs auf die Datei.
LastWriteTime Liefert oder setzt die Zeit des letzten schreibenden Zugriffs auf die Datei.
Length Gibt die Länge der Datei zurück.
Name Gibt den vollständigen Namen der Datei zurück.

Wir wollen uns aus der Tabelle die Eigenschaft Attributes, die ihrerseits vom Typ FileAttributes ist, genauer ansehen. Attributes beschreibt ein Bitfeld bestimmter Größe. Jedes Attribut einer Datei wird durch Setzen eines bestimmten Bits in diesem Bitfeld beschrieben. Um festzustellen, ob ein Dateiattribut gesetzt ist, muss das alle Attribute beschreibende Bitfeld mit dem gesuchten Dateiattribut bitweise »&«-verknüpft werden. Weicht das Ergebnis von null ab, ist das Bit gesetzt.

Dazu ein Zahlenbeispiel. Nehmen wir an, das Attribut XYZ würde durch die Bitkombination 0000 1000 (= 8) beschrieben und das Bitfeld würde aktuell 0010 1001 (= 41) enthalten. Um zu prüfen, ob das Attribut XYZ durch das Bitfeld beschrieben wird, gilt:


    0000 1000 
&   0010 1001
--------------
=   0000 1000 

Das Ergebnis ist nicht null und so zu interpretieren, dass das Attribut im Bitfeld gesetzt ist.

Um aus einer Datei ein bestimmtes Attribut herauszufiltern, beispielsweise Hidden, müssten wir daher wie folgt vorgehen:


FileInfo f = new FileInfo(@"C:\Testfile.txt");
if (0 != (f.Attributes & FileAttributes.Hidden)) {
  // Datei ist versteckt (hidden)
}

Soll das Attribut gesetzt werden, bietet sich der »^«-Operator an:


f.Attributes = f.Attributes ^ FileAttributes.Hidden;

In gleicher Weise können Sie mit den Methoden GetAttributes und SetAttributes der Klasse File arbeiten.

Die Methoden eines »FileInfo«-Objekts

Die Klassen File und FileInfo sind sich in den Funktionalitäten, die dem Entwickler angeboten werden, sehr ähnlich: Es lassen sich Dateien löschen, verschieben, umbenennen, kopieren, öffnen usw. Die meisten geben ein Stream-Objekt für weitergehende Operationen zurück.


Tabelle 12.6   Die Methoden eines Objekts vom Typ »FileInfo«

Methode Rückgabetyp Beschreibung
AppendText StreamWriter Hängt Text an eine existierende Datei an.
CopyTo FileInfo Kopiert die Datei an eine andere Speicherlokalität.
Create FileStream Erzeugt eine Datei.
CreateText StreamWriter Erzeugt eine neue Textdatei.
Delete Löscht die Datei.
Exists Boolean Gibt einen booleschen Wert zurück, der false ist, wenn die angegebene Datei nicht existiert.
MoveTo Verschiebt die Datei in einen anderen Ordner oder benennt sie um.
Open FileStream Öffnet eine Datei.
OpenRead FileStream Öffnet eine Datei zum Lesen.
OpenText StreamReader Öffnet eine Textdatei zum Lesen.
OpenWrite FileStream Öffnet eine Datei zum Schreiben.


Galileo Computing

12.2.3 Die Klassen »Directory« und »DirectoryInfo«  downtop

Die Klasse File veröffentlicht statische Methoden, um mit Dateien zu operieren, die Klasse FileInfo beschreibt die Referenz auf ein konkretes Dateiobjekt. Mit den Klassen Directory und DirectoryInfo wird dem auf Basis der Verzeichnisstruktur jeweils ein Gegenpart gegenübergestellt: Directory veröffentlicht nur Klassenmethoden, DirectoryInfo basiert auf einer konkreten Instanz. Es stellt sich natürlich sofort die Frage, warum die Architekten der Klassenbibliothek jeweils zwei Klassen mit nahezu gleichen Fähigkeiten vorgesehen haben.

Der entscheidende Unterschied liegt in der Art und Weise, wie die Klassen im Hintergrund arbeiten. Zugriffe auf das Dateisystem setzen immer operative Berechtigungen voraus. Verfügt der Anwender nicht über die entsprechenden Rechte, wird die angeforderte Aktion abgelehnt. Die beiden Klassen File und Directory prüfen das bei jedem Zugriff erneut und belasten so das System unnötig, während die Überprüfung von den Klassen DirectoryInfo und FileInfo nur einmal ausgeführt wird.

Mit Directory kann man Ordner anlegen, löschen oder verschieben, die in einem Verzeichnis physikalisch gespeicherte Dateinamen abrufen, verzeichnisspezifische Eigenschaften sowie das Erstellungsdatum oder das Datum des letzten Zugriffs ermitteln. Die folgende Tabelle 12.7 liefert einen unvollständigen Überblick über die Methoden von Directory.


Tabelle 12.7   Methoden der Klasse »Directory«

Methode Beschreibung
CreateDirectory Erzeugt ein Verzeichnis oder Unterverzeichnis.
Delete Löscht ein Verzeichnis.
Exists Überprüft, ob das angegebene Verzeichnis existiert.
GetCreationTime Liefert das Erstellungsdatum samt Uhrzeit.
GetDirectories Liefert die Namen aller Unterverzeichnisse eines spezifizierten Ordners.
GetFiles Liefert alle Dateinamen eines spezifizierten Ordners zurück.
GetFileSystemEntries Liefert die Namen aller Unterverzeichnisse und Dateien eines spezifizierten Ordners.
GetParent Liefert den Namen des übergeordneten Verzeichnisses.
Move Verschiebt ein Verzeichnis samt Dateien an eine neue Speicherlokalität.
SetCreationTime Legt Datum und Uhrzeit eines Verzeichnisses fest.

Die Fähigkeiten der Klasse DirectoryInfo ähneln denen von Directory, setzen jedoch ein konkretes Objekt für den Zugriff auf die Elementfunktionen voraus.

Im folgenden Beispiel werden einige Methoden und Eigenschaften der Klassen File, FileInfo und Directory benutzt. Das Programm fordert den Anwender dazu auf, an der Konsole ein beliebiges Verzeichnis anzugeben, dessen Unterverzeichnisse und Dateien ermittelt und unter der Angabe der Dateigröße und der Dateiattribute an der Konsole ausgegeben werden.


// ------------------------------------------------------------
// Beispiel: ...\Kapitel 12\FileDirectoryDemo
// ------------------------------------------------------------
class Program {
  public static void Main() {
    DirectoryTest dirTest = new DirectoryTest();
    FileInfo myFile;
    // Benutzereingabe anfordern
    string path = dirTest.PathInput();
    int len = path.Length;
    // alle Ordner und Dateien holen
    string[] str = Directory.GetFileSystemEntries(path);
    Console.WriteLine();
    Console.WriteLine("Ordner und Dateien im Verzeichnis {0}", path);
    Console.WriteLine(new string('-', 80));
    for (int i = 0; i <= str.GetUpperBound(0); i++) {
      // prüfen, ob der Eintrag ein Verzeichnis oder eine Datei ist
      if(0 == (File.GetAttributes(str[i]) & FileAttributes.Directory)) {
        // str(i) ist kein Verzeichnis
        myFile = new FileInfo(str[i]);
        string fileAttr = dirTest.GetFileAttributes(myFile);
        Console.WriteLine("{0,-30}{1,25} kB {2,-10} ", 
                                    str[i].Substring(len – 1), 
                                    myFile.Length / 1024, 
                                    fileAttr);
      }
      else
        Console.WriteLine("{0,-30}{1,-15}", str[i].Substring(len), "Dateiordner");
    }
    Console.ReadLine();
  }
  // Benutzer zur Eingabe eines Pfads auffordern
  string PathInput() {
    Console.Write("Geben Sie den zu durchsuchenden ");
    Console.Write("Ordner an: ");
    string searchPath = Console.ReadLine();
    // wenn die Benutzereingabe als letztes Zeichen kein'\' 
    // enthält, muss dieses angehängt werden
    if(searchPath.Substring(searchPath.Length – 1) != "\\")
      searchPath += "\\";
    return searchPath;
  }
  // Feststellung, welche Dateiattribute gesetzt sind
  // Rückgabe eines Strings, der die gesetzten Attribute enthält
  string GetFileAttributes(FileInfo strFile) {
    string strAttr;
    // prüfen, ob Archive-Attribut gesetzt ist
    if(0 != (strFile.Attributes & FileAttributes.Archive))
      strAttr = "A ";
    else
      strAttr = "  ";
    // prüfen, ob Hidden-Attribut gesetzt ist
    if(0 != (strFile.Attributes & FileAttributes.Hidden))
      strAttr += "H ";
    else
      strAttr += "  ";
    // prüfen, ob ReadOnly-Attribut gesetzt ist
    if(0 != (strFile.Attributes & FileAttributes.ReadOnly))
      strAttr += "R ";
    else
      strAttr += "  ";
    // prüfen, ob System-Attribut gesetzt ist
    if(0 != (strFile.Attributes & FileAttributes.System))
      strAttr += "S ";
    else
      strAttr += "  ";
    return strAttr;
  }
}

Starten Sie die Anwendung, könnte die Ausgabe an der Konsole ungefähr wie in der folgenden Abbildung dargestellt aussehen.

Abbildung
Hier klicken, um das Bild zu vergrößern

Abbildung 12.2   Ausgabe des Beispiels »FileDirectoryDemo«

Das gesamte Projekt ist in der Klasse DirectoryTest realisiert. Die Klasse enthält neben der statischen Methode Main die Methoden PathInput und GetAttributes. Die Methode PathInput liefert eine Zeichenfolge zurück, die den Pfad des Verzeichnisses enthält, dessen Inhalt abgefragt werden soll. Wichtig ist im Kontext des Beispiels, die Rückgabezeichenfolge mit einem Backslash abzuschließen, da ansonsten die spätere Ausgabe an der Konsole nicht immer gleich aussieht.

GetFileSystemEntries liefert als Ergebnis des Aufrufs ein String-Array, das dem Feld str zugewiesen wird.


string str = Directory.GetFileSystemEntries(path);

Jedes Element des Arrays kann sowohl eine Datei- als auch eine Verzeichnisangabe enthalten. Daher wird in einer for-Schleife das Array vom ersten bis zum letzten Element durchlaufen, um festzustellen, ob das Element eine Datei oder ein Verzeichnis beschreibt. Handelt es sich um ein Verzeichnis, ist das Attribut Directory gesetzt. Mit


if(0 == (File.GetAttributes(str[i]) & FileAttributes.Directory))

wird das geprüft. Die Bedingung ist liefert true, wenn eine Datei vorliegt.

Nun folgt ein ganz entscheidender Punkt. Da das Programm die Größe der Datei ausgeben soll, können wir nicht mit File arbeiten, da in dieser Klasse keine Methode vorgesehen ist, die uns die Länge der Datei liefert. Dies ist nur über eine Instanz der Klasse FileInfo mit der Auswertung der schreibgeschützten Eigenschaft Length möglich, die bei jedem Schleifendurchlauf auf eine andere Datei verweist.

Die benutzerdefinierte Methode GetAttributes dient dazu, das übergebene FileInfo-Objekt auf die Attribute Hidden, ReadOnly, Archive und System hin zu untersuchen. Aus dem Ergebnis wird eine Zeichenfolge zusammengesetzt, die den Anforderungen der Anwendung entspricht. Zum Schluss erfolgt noch die formatierte Ausgabe an der Konsole. Für den Verzeichnis- bzw. Dateinamen ist eine maximale Breite von 30 Zeichen vorgesehen. Ist dieser Wert größer, ist das Ergebnis eine zwar etwas unansehnliche Ausgabe, aber unseren Ansprüchen soll sie genügen.


Galileo Computing

12.2.4 Die Klasse »Path«  downtop

Eine Pfadangabe beschreibt die Lokalität einer Datei oder eines Verzeichnisses. Die Schreibweise der Pfadangabe wird vom Betriebssystem vorgegeben und ist nicht auf allen Plattformen zwangsläufig identisch. Bei manchen Systemen muss die Pfadangabe mit dem Laufwerksbuchstaben beginnen, bei anderen Systemen ist das nicht unbedingt vorgeschrieben. Pfadangaben können sich auch auf Dateien beziehen. Es gibt Systeme, die ermöglichen als Dateierweiterung zur Beschreibung des Dateityps maximal drei Buchstaben, während andere durchaus mehr zulassen.

Das sind nicht die einzigen Unterscheidungsmerkmale, die plattformspezifisch sind. Denken Sie nur an die Separatoren, mit denen zwei Verzeichnisse oder ein Verzeichnis von einer Datei getrennt werden. Windows-basierte Plattformen benutzen dazu das Zeichen Backslash (\), andere Systeme schreiben einen einfachen Slash (/) vor.

Die Klassen File und Directory greifen immer wieder auf Pfadangaben zurück. Da die Architektur der .NET-Plattform plattformneutral ist, muss dem Umstand der verschiedenen Vorschriften einer Pfadbeschreibung Rechnung getragen werden. Hieraus bezieht die nicht ableitbare Klasse Path ihre Existenzberechtigung, die Operationen auf Zeichenfolgen unterstützt, die Datei- oder Verzeichnisinformationen enthalten. Zudem werden auch Operationen angeboten, um einzelne Informationen aus der Pfadangabe herauszufiltern, und – was auch von großer Wichtigkeit sein kann – die Methoden von Path können benutzt werden, um den Pfad zum temporären Verzeichnis zu erhalten.

Methoden der Klasse »Path«

Alle Path-Klassenmitglieder sind statisch und haben die Aufgabe, eine Pfadangabe in einer bestimmten Weise zu filtern. Sie benötigen daher keine Instanz der Klasse Path, um auf ein Feld oder eine Methode dieser Klasse zugreifen zu können.


Tabelle 12.8   Methoden der Klasse »Path«

Methode Beschreibung
GetDirectoryName Liefert aus einer gegebenen Pfadangabe das Verzeichnis zurück.
GetExtension Liefert aus einer gegebenen Pfadangabe die Dateierweiterung einschließlich des führenden Punktes zurück.
GetFileName Liefert den vollständigen Dateinamen zurück.
GetFileNameWithoutExtension Liefert den Dateinamen ohne Dateierweiterung zurück.
GetFullPath Liefert die komplette Pfadangabe zurück.
GetPathRoot Liefert das Stammverzeichnis.

Beachten Sie dabei, dass keine dieser Methoden testet, ob die Datei oder das Verzeichnis tatsächlich existiert. Es werden lediglich die Zeichenkette und die Vorschriften der spezifischen Plattform zur Bestimmung des Ergebnisses herangezogen.

Mit


string strPath = @"C:\winnt\system\OLE2.dll"

liefern die Methoden die folgenden Rückgaben:


Console.WriteLine(Path.GetPathRoot(strPath));
// liefert C:\
Console.WriteLine(Path.GetDirectoryName(strPath));
// liefert C:\winnt\system
Console.WriteLine(Path.GetFileNameWithoutExtension(strPath));
// liefert OLE2
Console.WriteLine(Path.GetFileName(strPath));
// liefert OLE2.dll
Console.WriteLine(Path.GetFullPath(strPath));
// liefert C:\winnt\system\OLE2.dll
Console.WriteLine(Path.GetExtension(strPath));
// liefert .dll

Temporäre Verzeichnisse

Sehr viele Anwendungen arbeiten mit Verzeichnissen, in die Dateien temporär, also nicht dauerhaft geschrieben werden. Die Klasse Path bietet mit GetTempPath eine Methode an, die das temporäre Verzeichnis des aktuell angemeldeten Benutzers liefert.


public static string GetTempPath();

 

Unter Windows 2000/XP ist dieses Verzeichnis standardmäßig unter dem Namen Temp in


C:\Dokumente und Einstellungen\Username\Lokale Einstellungen

zu finden.

Mit GetTempFileName wird eine leere Datei im temporären Verzeichnis angelegt, der Rückgabewert ist die komplette Pfadangabe:


public static string GetTempFileName();

Eine temporäre Datei kann von den anderen Methoden dazu benutzt werden, Zwischenergebnisse zu speichern, Informationen kurzfristig zu sichern und Abläufe zu protokollieren. Allerdings sollten Sie nicht vergessen, temporäre Dateien auch wieder zu löschen, wenn sie nicht mehr benötigt werden.


Galileo Computing

12.2.5 Die Klasse »DriveInfo«  downtop

Sich mit .NET Framework 1.0/1.1 Laufwerksinformationen zu besorgen, war nicht ganz einfach. Eine speziell darauf zugeschnittene Klasse gab es nicht. So blieb keine andere Möglichkeit, als den Umweg über die Win32-API zu gehen, um sich die gewünschten oder erforderlichen Daten zu besorgen. In der aktuellen Version 2.0 wurde diese Lücke mit der neuen Klasse DriveInfo gefüllt.

Mit DriveInfo können Sie bestimmen, welche Laufwerke verfügbar sind und um welchen Typ von Laufwerk es sich dabei handelt. Zudem können Sie mit Hilfe einer Abfrage die Kapazität und den verfügbaren freien Speicherplatz auf dem Laufwerk ermitteln.


Tabelle 12.9   Eigenschaften der Klasse »DriveInfo«

Eigenschaft Rückgabetyp Beschreibung
AvailableFreeSpace long Gibt die Menge an verfügbarem freien Speicherplatz auf einem Laufwerk an.
DriveFormat string Ruft den Namen des Dateisystems ab.
DriveType DriveType Ruft den Laufwerktyp ab.
IsReady bool Der Rückgabewert gibt an, ob das Laufwerk bereit ist.
Name string Liefert den Namen des Laufwerks.
RootDirectory DirectoryInfo Liefert das Stammverzeichnis des Laufwerks.
TotalFreeSpace long Liefert den verfügbaren Speicherplatz.
TotalSize long Ruft die Gesamtgröße des Speicherplatzes auf einem Laufwerk ab.
VolumeLabel string Ruft die Datenträgerbezeichnung eines Laufwerks ab.

Die Eigenschaft DriveType sollten wir uns noch etwas genauer ansehen. Sie liefert als Ergebnis des Aufrufs eine Konstante der gleichnamigen Enumeration ab. Diese hat insgesamt sieben Mitglieder, die Sie der folgenden Tabelle entnehmen können.


Tabelle 12.10   Mitglieder der Enumeration »DriveType«

Member Beschreibung
CDRom Optischer Datenträger (z.B. CD oder DVD)
Fixed Festplatte
Network Netzlaufwerk
NoRootDirectory Das Laufwerk hat kein Stammverzeichnis.
Ram RAM-Datenträger
Removable Wechseldatenträger
Unknown Unbekannter Laufwerkstyp


Galileo Computing

12.2.6 Die Klasse »SpecialDirectories«  toptop

Eine zweite neue Klasse, die dem Bereich Laufwerke, Ordner und Dateien zugeordnet werden kann, ist SpecialDirectories. Sie dient der Ermittlung Windows-spezifischer Pfade, zum Beispiel den zu »Eigene Bilder«. Die Angaben werden über statische Eigenschaften als Zeichenfolge geliefert.


Tabelle 12.11   Mitglieder der Enumeration »DriveType«

Eigenschaft Beschreibung
AllUserApplicationData Ruft einen Pfadnamen ab, der auf die Anwendungsdaten im Verzeichnis »\Dokumente und Einstellungen\All Users\Anwendungsdaten« zeigt.
CurrentUserApplicationData Ruft einen Pfadnamen ab, der auf das Verzeichnis »Anwendungsdaten des aktuellen Benutzers« zeigt.
Desktop Ruft den Pfad des »Desktop«-Verzeichnisses ab.
MyDocuments Ruft den Pfad des »Eigene Dateien«-Verzeichnisses ab.
MyMusic Ruft den Pfad des »Eigene Musik«-Verzeichnisses ab.
MyPictures Ruft den Pfad des »Eigene Bilder«-Verzeichnisses ab.
ProgramFiles Ruft den Pfad des »Program Files«-Verzeichnisses ab.
Programs Ruft den Pfad des »Programme«-Verzeichnisses ab.
Temp Ruft den Pfad des »Temp«-Verzeichnisses ab.

Beabsichtigen Sie, diese Klasse einzusetzen, müssen Sie zuerst unter Verweise im Projektmappen-Explorer die Datei Microsoft.VisualBasic.dll einbinden. Zusätzlich sollten Sie auch den Namespace Microsoft.VisualBasic.FileIO bekannt geben. Weshalb die doch sehr interessante Klasse diesem Namespace zugeordnet worden ist, bleibt ein Geheimnis.

 

 << zurück
  
  Zum Katalog
Zum Katalog: Visual C# 2005
Visual C# 2005
bestellen
 Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchtipps
Zum Katalog: Fortgeschrittene Programmierung mit Visual C# 2005






 Fortgeschrittene
 Programmierung
 mit Visual C# 2005


Zum Katalog: Einstieg in Visual C# 2005






 Einstieg in
 Visual C# 2005


Zum Katalog: Einstieg in Visual Basic 2005






 Einstieg in
 Visual Basic 2005


Zum Katalog: Visual Basic 2005






 Visual Basic 2005


Zum Katalog: Java ist auch eine Insel






 Java ist auch eine
 Insel


Zum Katalog: Konzepte und Lösungen für Microsoft-Netzwerke






 Konzepte und
 Lösungen für
 Microsoft-Netzwerke


 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
InfoInfo








Copyright © Galileo Press 2006
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


[Galileo Computing]

Galileo Press, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, info@galileo-press.de